openapi: 3.0.3
info:  
  title: "PSA Verification of Payee - version 1.0.8 - 20250324"
  version: "1.0.9"
  description: |
    Technical specification for the VoP Application Programming Interface
    
    SINGLE REQUESTS
    
    CHANGES SINCE 1.0.8
    
    Correct BICType pattern to comply with ISO\
    
    CHANGES SINCE 1.0.7
    
    Add second server URL and description to URL use cases\
    Add optional header 'X-Request-Account-Servicer-BIC' to post /payee-verifications for requests by PSA VoP Service Members\
    Add http 421 error possibility and description\
    Rework enum of messageCode to reflect possibilities and description\
    Rework examples of verificationOfPayeeError\
    Add missing requirement of requestingAgent in verificationOfPayeeRequest\
    Add description to requestingAgent of post /payee-verifications\
    Rework position of errors and connected examples
    
  contact:
    name: 'PSA Payment Services Austria'
    url: 'https://www.psa.at/'
    email: 'office@psa.at'
    x-team-info:
      department: 'Account Systems'
      colleagues: 'Alexandra Karrer, Hendrik Muus, Marinko Ostojić'
externalDocs:
  description: |
    Verification of Payee PSA API description based on
    
    Verification Of Payee Scheme Rulebook - EPC218-23
    
    Verification Of Payee Inter-PSP API Specification - EPC103-24
    
    EPC API Security Framework - EPC164-22
    
  url: 'https://www.europeanpaymentscouncil.eu/what-we-do/other-schemes/verification-payee'
servers:
- url: https://api.vop.psa.at/{BIC}/vop/v1
  description: For requests from requesters not being a PSA VoP member
    {BIC} needs being replaced by the BIC (11) of the PSA VoP member the VoP request is directed to
- url: https://api.vop.psa.at/PSSAATWWXXX/vop/v1
  description: For requests from requesters being a PSA VoP member
- url: https://api-test.vop.psa.at/PSSAATWWXXX/vop/v1
  description: For requests from requesters being a PSA VoP member in staging environment
paths:
  /payee-verifications:
    description: |
      Financial institution's VoP request, that need to be answered within 3 seconds, allowing for an overall 5 seconds from customers input to output to customer
    post:
      operationId: postVerificationOfPayeeRequest
      parameters:
      - $ref: '#/components/parameters/requestResponseId'
      - $ref: '#/components/parameters/requestTimestamp'
      - $ref: '#/components/parameters/requestAccountServicerBic'
      - $ref: '#/components/parameters/responseNotTimeCritical'
      requestBody:
        $ref: '#/components/requestBodies/singleRequest'
      responses:
        '200':
          $ref: '#/components/responses/singleResponse'
        '400':
          $ref: '#/components/responses/errors'
        '401':
          $ref: '#/components/responses/errors'
        '403':
          $ref: '#/components/responses/errors'
        '404':
          $ref: '#/components/responses/errors'
        '409':
          $ref: '#/components/responses/errors'
        '421':
          $ref: '#/components/responses/errors'
        '500':
          $ref: '#/components/responses/errors'
components:
  headers:
    requestResponseId:
      description: |
        The Requester's reference number of the VoP Request Message
      required: true
      schema:
        $ref: '#/components/schemas/UUIDType'
    responseTimestamp:
      description: |
        The Requester's timestamp of the VoP Request Message
      schema:
        $ref: '#/components/schemas/dateTimeType'
      required: true
  parameters:
    responseNotTimeCritical:
      description: |
        Indicator, whether response is released from standard response time frame and may take longer. Allow other requests to be prioritised. Time frame for indicated requests is extended to 58 seconds.
      in: header
      required: false
      name: X-Request-NTC
      schema:
        type: boolean
        example: 'true'
    requestAccountServicerBic:
      description: |
        The BIC of the account servicing bank serviced by 'participantBIC' according EDS entry 'accountHoldingBIC' at EPC
        This BIC is used for internal processes for PSA VoP Service Members and mandatory if ASPSP request uses participants BIC in VoP request
      in: header
      required: false
      name: X-Request-Account-Servicer-BIC
      schema:
        $ref: '#/components/schemas/BICType'
    requestResponseId:
      description: |
        The Requester's reference number of the VoP Request Message
      in: header
      required: true
      name: X-Request-ID
      schema:
        $ref: '#/components/schemas/UUIDType'
    requestTimestamp:
      description: |
        The Requester's timestamp of the VoP Request Message
      in: header
      required: true
      name: X-Request-Timestamp
      schema:
        $ref: '#/components/schemas/dateTimeType'
  requestBodies:
    singleRequest:
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/verificationOfPayeeRequest'
      required: true
  responses:
    errors:
      description: |
        Error according descriptive content. May occur from outside application too.\
      headers:
        X-Request-ID:
          $ref: '#/components/headers/requestResponseId'
        X-Response-Timestamp:
          $ref: '#/components/headers/responseTimestamp'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/verificationOfPayeeError'
          examples:
            400:
              description: |
                Bad Request - malformed payload.
              value:
                type: "https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/400"
                code: "FORMAT_ERROR"
                title: "Malformed JSON"
                status: 400
                detail: "Request Body could not be parsed or otherwise recognised"
                instance: 
            400_b:
              description: |
                Bad Request - malformed payload.
              value:
                type: "https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/400"
                code: "TIMESTAMP_INVALID"
                title: "Timestamp not accepted"
                status: 400
                detail: "Diviation between timestamp and current time is out of accepted bounds"
                instance: 
            400_c:
              description: |
                Bad Request - malformed payload.
              value:
                type: "https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/400"
                code: "UNKNOWN_ERROR"
                title: "Unspecific error condition"
                status: 400
                detail: "Request Body could not be parsed or otherwise recognised"
                instance: 
            401:
              description: |
                Unauthorized - not correctly authenticated to perform the request, e.g. no certificate, not accepted certificate type, etc.\
              value:
                type: "https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/401"
                code: "CLIENT_INVALID"
                title: "Authorisation failed"
                status: 401
                detail: "No certificate or unfitting certificate type used"
                instance: 
            403:
              description: |
                Forbidden - authorisation issue, certificate not acceptable, e.g. certificate's NAN do not match BIC in request, etc.\

              value:
                type: "https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/403"
                code: "CLIENT_INCONSISTENT"
                title: "NAN and BIC don't match"
                status: 403
                detail: "BIC derived from NAN of certificate doesn't match BIC in request"
                instance: 
            404:
              description: |
                Not Found - resource not existing, e.g. resource according path in request not existing.\
              value:
                type: "https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/404"
                code: "NOT_FOUND"
                title: "Cannot find the requested resource"
                status: 404
                detail: "Resource is missing or has never existed"
                instance: 
            409:
              description: |
                Conflict - header carry duplicate entry, i.e. request id already used.\
              value:
                type: "https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/409"
                code: "DUPLICATE"
                title: "RequestId already in use"
                status: 409
                detail: "The request identification is already in use and therefore cannot be accepted"
                instance: 
            421:
              description: |
                Misdirected Request - request was directed to wrong server, i.e. none of the BICs is service member.\
              value:
                type: "https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/421"
                code: "MISDIRECTED_REQUEST"
                title: "Cannot provide information requested"
                status: 421
                detail: "Requester responder combination unsupported"
                instance: 
            422:
              description: |
                Unprocessable Content - content of request not fitting process requirements, e.g. inconsistent, contradicting or ambiguous.\
              value:
                type: "https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/422"
                code: "RESOURCE_NOT_FOUND"
                title: "Resource according Id not found"
                status: 422
                detail: "Transmitted resource Id not fount among available resource Ids"
                instance: 
            451:
              description: |
                Unavailable For Legal Reasons - owner of NAN not supported, e.g. missing agreement may lead to GDPR issues.\
              value:
                type: "https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/451"
                code: "CLIENT_UNKNOWN"
                title: "NAN not registered"
                status: 451
                detail: "The NAN given in certificate is not listed in list of supported requester's NANs"
                instance: 
            500:
              description: |
                Internal Server Error - technical problem occurred in the application code or application server preventing request execution.
              value:
                type: "https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/500"
                code: "SERVER_ERROR"
                title: "Internal error occurred while processing request"
                status: 500
                detail: "Server reported an error during computing. Technical personal has been informed about this issue"
                instance: 
    singleResponse:
      description: |
        A verification code and possible additional information assigned by the Responder
      headers:
        X-Request-ID:
          $ref: '#/components/headers/requestResponseId'
        X-Response-Timestamp:
          $ref: '#/components/headers/responseTimestamp'
      content:
        application/json:
           schema:
            $ref: '#/components/schemas/verificationOfPayeeResponse'
  schemas:
    BICType: 
      description: |
        Business Identifier Code according ISO 9362. May identify financial institutions and other organisations.
      type: string
      pattern: '^[A-Z0-9]{4}[A-Z]{2}[A-Z0-9]{2}([A-Z0-9]{3})?$'
      example: 'ABCDBEBBFIM'
    IBANType: 
      description: |
        InternationalBankAccountNumber according ISO 13616, as assigned by the responding PSP.
      type: string
      pattern: '^[A-Z]{2}[0-9]{2}[A-Z0-9]{1,30}$'
      example: 'AB121234567812345678901234'
    LEIType: 
      description: |
        Code LEI (Legal Entity Identifier) according ISO 17442.
      type: string
      pattern: '^[A-Z0-9]{18}[0-9]{2}$'
      example: '549300DTUYXVMJXZNY75'
    UUIDType:
      description: | 
        A UUID according RFC 4122 Version 4.
      type: string
      format: uuid
      pattern: '^[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$'
      example: '9f45a3e5-aa49-43d6-9f1c-36ae3b5a295e'
    accountType:
      description: |
        InternationalBankAccountNumber according ISO 13616, as assigned by the responding PSP.
      type: object
      properties:
        iban:
          $ref: '#/components/schemas/IBANType' 
      required:
        - iban
    agentType:
      description: |
        Financial Institution Identifier within clearing and/or settlement systems.
      type: object
      properties:
        financialInstitutionId:
          $ref: '#/components/schemas/financialInstitutionId'
      required:
        - financialInstitutionId
    dateTimeType:
      description: |
        Timestamp in ISO 8601 format, either UTC (YYYY-MM-DDThh:mm:ss.sssZ) or local time with UTC offset (YYYY-MM-DDThh:mm:ss.sss+/-hh:mm), milliseconds precision (observe truncation rules !).
      type: string
      format: date-time
      pattern: '^\d{4}(-\d{2}){2}T\d{2}(:\d{2}){2}(\.\d{0,2}[1-9])?(Z|([-+]\d{2}(:\d{2})?))$'
      example: '2024-12-12T12:12:12Z ; 2024-12-12T12:12:12.02Z ; 2024-12-12T12:12:10+02'
    financialInstitutionId:
      description: |
        Financial Institution Identifier within clearing and/or settlement systems.
      type: object
      properties:
        bicfi:
          $ref: '#/components/schemas/BICType'
      required:
        - bicfi
    genericOrganisationId:
      description: | 
        An organisation identifier and an identifier type qualified by either ‘schemeNameCode’ or ‘schemeNameProprietary’ and optionally an identifier issuer information
      oneOf:
        - $ref: '#/components/schemas/organisationCodedId'
        - $ref: '#/components/schemas/organisationProprietaryId'
    idAsLEI:
      description: |
        Legal Entity Identifier according ISO 17442.
      type: object
      properties:
        lei:
          $ref: '#/components/schemas/LEIType'
    idAsBIC:
      description: |
        Business Identifier Code according ISO 9362. May identify financial institutions and other organisations.
      type: object
      properties:
        anyBIC:
          $ref: '#/components/schemas/BICType'
    idAsOther:
      description: | 
        An organisation identifier and an identifier type qualified by either ‘schemeNameCode’ or ‘schemeNameProprietary’ and optionally an identifier issuer information. Although the structure is an array, only one identifier is allowed
      type: object
      properties:
        others:
          type: array
          items:
            $ref: '#/components/schemas/genericOrganisationId'
          maxItems: 1
    idType:
      description: | 
        Unique identification of an organisation, as assigned by an institution, using an identification scheme.
      type: object
      properties:
        organisationId:
          $ref: '#/components/schemas/organisationIdType'
      required:
        - organisationId
    max140Text:
      type: string
      minLength: 1
      maxLength: 140
    max256Text:
      type: string
      minLength: 1
      maxLength: 256
    max35Text:
      type: string
      minLength: 1
      maxLength: 35
    max500Text:
      type: string
      minLength: 1
      maxLength: 500
    max70Text:
      type: string
      minLength: 1
      maxLength: 70
    messageCode:
      description: | 
        Specifies the codes Error messages.
      type: string
      enum: [FORMAT_ERROR, TIMESTAMP_INVALID, UNKNOWN_ERROR, CLIENT_INVALID, CLIENT_INCONSISTENT, NOT_FOUND, DUPLICATE, MISDIRECTED_REQUEST, RESOURCE_NOT_FOUND, CLIENT_UNKNOWN, SERVER_ERROR]
      example: 'TIMESTAMP_INVALID'
    nameMatchType:
      description: | 
        Specifies the codes -in sequence- for Match, NoMatch and MatchNotApplicable.
      type: string
      enum: [MTCH, NMTC, NOAP]
      example: 'MTCH'
    nameMatchTypeClose:
      description: | 
        Specifies the code CloseMatch.
      type: string
      enum: [CMTC]
      example: 'CMTC'
    organisationCodedId:
      description: |
        Unique and unambiguous identification of an organisation according provided coded scheme within issuers space.
      type: object
      properties:
        identification:
          $ref: '#/components/schemas/max256Text'
        schemeNameCode:
          $ref: '#/components/schemas/organisationIdCode'
        issuer:
          $ref: '#/components/schemas/max35Text'
      required:
        - identification
        - schemeNameCode
    organisationIdCode:
      description: |
        Specifies the external organisation identification scheme name code (maximum 4 characters) as defined in an external list (iso20022.org).
      type: string
      enum: [BANK, CBID, CHID, CINC, COID, CUST, DUNS, EMPL, GS1G, SREN, SRET, TXID, BDID, BOID]
      example: 'BOID'
    organisationIdType:
      description: | 
        Unique identification of an organisation, as assigned by an institution, using an identification scheme.
      oneOf:
        - $ref: '#/components/schemas/idAsLEI'
        - $ref: '#/components/schemas/idAsBIC'
        - $ref: '#/components/schemas/idAsOther'
    organisationProprietaryId:
      description: |
        Unique and unambiguous identification of an organisation according provided proprietary scheme eventually within issuers space.
      type: object
      properties:
        identification:
          $ref: '#/components/schemas/max256Text'
        schemeNameProprietary:
          $ref: '#/components/schemas/max35Text'
        issuer:
          $ref: '#/components/schemas/max35Text'
      required:
        - identification
        - schemeNameProprietary
    partyAsId:
      description: | 
        A party is identified by an identifier.
      type: object
      properties:
        identification:
          $ref: '#/components/schemas/idType'
      required:
        - identification
    partyAsName:
      description: | 
        A party is identified by a name.
      type: object
      properties:
        name:
          $ref: '#/components/schemas/max140Text'
      required:
        - name
    partyIdMatchType:
      description: | 
        Specifies the codes -in sequence- for Match, NoMatch and MatchNotApplicable.
      type: string
      enum: [MTCH, NMTC, NOAP]  
      example: 'MTCH'
    partyType:
      description: | 
        A party is either identified by a name or by an identifier.
      oneOf:
        - $ref: '#/components/schemas/partyAsName'
        - $ref: '#/components/schemas/partyAsId'
    verificationOfId:
      description: |
        Defined codes for IBAN - Id verification.
      type: object
      properties:
        partyIdMatch:
          $ref: '#/components/schemas/partyIdMatchType'
      required:
        - partyIdMatch
    verificationOfName:
      description: |
        Defined codes for IBAN - Name verification (not including close match).
      type: object
      properties:
        partyNameMatch:
          $ref: '#/components/schemas/nameMatchType'
      required:
        - partyNameMatch
    verificationOfNameClose:
      description: |
        Defined code for IBAN - Name verification on close match together with proposed name.
      type: object
      properties:
        partyNameMatch:
          $ref: '#/components/schemas/nameMatchTypeClose'
        matchedName:
          $ref: '#/components/schemas/max140Text'
      required:
        - partyNameMatch
        - matchedName
        - partyAgent
    verificationOfPayeeError:
      description: |
        Provides information on an error occurred.
      type: object
      properties:
        type: 
          $ref: '#/components/schemas/max70Text'
        code:
          $ref: '#/components/schemas/messageCode'
        title:
          $ref: '#/components/schemas/max70Text'
        status:
          type: integer
          enum: [400,401,403,404,409,421,422,451,500]
        detail:
          $ref: '#/components/schemas/max500Text'
        instance:
          $ref: '#/components/schemas/max256Text'
      required:
        - type
        - code
    verificationOfPayeeRequest:
      description: | 
        Request for the verification process.
      type: object
      properties:
        party:
          $ref: '#/components/schemas/partyType'
        partyAccount: 
          $ref: '#/components/schemas/accountType'
        partyAgent: 
          $ref: '#/components/schemas/agentType'
        unstructuredRemittanceInformation:
          description: | 
            Additional information about AT-C001 sent by the Requester AT-C007. Although the structure is an array, only one item is allowed
          type: array
          items:
            $ref: '#/components/schemas/max140Text'
          maxItems: 1
        requestingAgent: 
          description: |
            The BIC of the requester registered as 'participantBIC' in EDS of EPC. BIC of account servicing banks registered as 'accountHoldingBIC' in EDS of EPC cannot be used for requesting agent. Account servicing banks need to use 'participantBIC' to which they are registered\
            In case of PSA VoP Members additional Header X-Request-Account-Servicer-BIC is used to qualify the account servicer
          allOf:
            - $ref: '#/components/schemas/agentType'
      required:
        - party
        - partyAccount
        - partyAgent
        - requestingAgent
    verificationOfPayeeResponse:
      description: | 
        Result of the verification process.
      oneOf:
        - $ref: '#/components/schemas/verificationOfName'
        - $ref: '#/components/schemas/verificationOfNameClose'
        - $ref: '#/components/schemas/verificationOfId'